﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace CommonLib {
    public class Scene {
        public const int GRIDSIZE = 8;
        private Primitive[] primitive;
        private Primitive[] lights;
        private Grid grid;

        public Scene()
        {
            initialize();
        }

        public Grid Grid { get { return this.grid; } }
        public Primitive[] Primitives { get { return this.primitive; } }
        public Primitive[] Lights { get { return this.lights; } }
        private void initialize() {
            List<Primitive> prims = new List<Primitive>();
            List<Primitive> lis = new List<Primitive>();

            // ground plane
            Primitive plane01 = new Plane(new Vector3c(0, -4.4, 0), new Vector3c(0, 1, 0), false);
            plane01.material = new Material(new Vector3c(0.4, 0.3, 0.3), 1.0, 0.0, 0.0, 1.0);
            prims.Add(plane01);

            // big sphere
            Primitive sphere01 = new Sphere(new Vector3c(0, 1, 7), 2, false);
            sphere01.material = new Material(new Vector3c(0.7, 0.7, 1.0), 0.2, 0.2, 0.8, 1.3);
            prims.Add(sphere01);

            // small sphere
            Primitive sphere02 = new Sphere(new Vector3c(-5, -0.8, 7), 2, false);
            sphere02.material = new Material(new Vector3c(0.5, 0.7, 1.0), 0.5, 0.05, 0.95, 1.3);
            sphere02.material.setTexture(new Texture("../../../textures/marble.tga"), 0.8, 0.8);
            sphere02.material.reflection = 0.0;
            sphere02.material.specular = 0.8;
            prims.Add(sphere02);

            // third sphere
            Primitive sphere03 = new Sphere(new Vector3c(5, -0.8, 7), 2, false);
            sphere03.material = new Material(new Vector3c(0.7, 0.7, 1.0), 0.1, 0.5, 0.5, 1.3);
            prims.Add(sphere03);

#if false
           // area light 01
            Primitive aabb01 = new AABB(
                new Cell(new Vector3c(-1, 4, 4), new Vector3c(2, 0.1, 2)), true);
            aabb01.material = new Material(new Vector3c(1, 1, 1), 0, 0, 0, 1.0);
            prims.Add(aabb01);
            // area light 02
            Primitive aabb02 = new AABB(
                new Cell(new Vector3c(3, 5, 4), new Vector3c(2, 0.1, 2)), true);
            aabb02.material = new Material(new Vector3c(1, 1, 1), 0, 0, 0, 1.0);
            prims.Add(aabb02);

#else
            // light source 1
            Primitive light01 = new Sphere(new Vector3c(0, 3, 5), 0.1, true);
            light01.material = new Material(new Vector3c(0.4, 0.4, 0.4), 0.0, 0.0, 0, 1.0);
            prims.Add(light01);
#endif

            // back plane
            Primitive plane02 = new Plane(new Vector3c(-4.457, 0, 11.142), new Vector3c(0.4, 0, -1), false);
            plane02.material = new Material(new Vector3c(0.5, 0.3, 0.5), 0.6, 0.0, 0.0, 1.0);
            plane02.material.setTexture(new Texture("../../../textures/marble.tga"), 0.1, 0.1);
            prims.Add(plane02);

            // ceiling plane
            Primitive plane03 = new Plane(new Vector3c(0, 7.4, 0), new Vector3c(0, -1, 0), false);
            plane03.material = new Material(new Vector3c(0.4, 0.7, 0.7), 0.5, 0.0, 0.0, 1.0);
            prims.Add(plane03);

            this.primitive = prims.ToArray();

            // cache lights
            for (uint i = 0; i < primitive.Length; i++)
                if (primitive[i].light == true)
                    lis.Add(primitive[i]);
            this.lights = lis.ToArray();

            // list primitives in grid
            BuildGrid();
        }
        public void BuildGrid() {
            Vector3c p1 = new Vector3c(-14, -5, -6);
            Vector3c p2 = new Vector3c(14, 8, 30);

            Vector3c dim = p2;
            dim.sub(p1);
            Cell gridBndry = new Cell(p1, dim);
            grid = new Grid(gridBndry, GRIDSIZE);
            grid.DeployPrimitives(primitive);
        }
    }
}
